﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;

namespace FolderTransfer
{
    public class Server
    {
        private IPAddress ip;

        public IPAddress Ip
        {
            get { return ip; }
        }
        private int port;

        public int Port
        {
            get { return port; }
        }
        private TcpListener tcpListener;

        private FolderClient folderClient;

        public FolderClient FolderClient
        {
            get { return folderClient; }
        }

        private FormMain formMain;

        public Server(FormMain formMain)
        {
            this.formMain = formMain;
        }

        public void Listen()
        {
            this.ip = Utils.GetHostIP();
            this.port = Utils.GetAvailablePort();
            tcpListener = new TcpListener(this.ip, this.port);
            tcpListener.Start();

            Thread listenThread = new Thread(ListenThread);
            listenThread.IsBackground = true;
            listenThread.Start();
        }

        private void ListenThread()
        {
            TcpClient tcpClient = null;
            while (true)
            {
                try
                {
                    tcpClient = tcpListener.AcceptTcpClient();//阻塞性方法
                    folderClient = new FolderClient(tcpClient, formMain, this);
                }
                catch (Exception)
                {
                    return;
                }
            }
        }

        public void Close()
        {
            tcpListener.Stop();
        }
        private DirectoryInfo dir;
        public void Send(string folderPath)
        {
            this.dir = new DirectoryInfo(folderPath);
            folderClient.SendString("AgreeOrNot");
            folderClient.SendString(dir.Name);
        }
        private long totalLen;
       
        private void GetTotalLen(DirectoryInfo dir)
        {
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                this.totalLen += file.Length;
            }
            DirectoryInfo[] dirs = dir.GetDirectories();
            foreach (DirectoryInfo dirInfo in dirs)
            {
                GetTotalLen(dirInfo);
            }
        }

        private int index;
        public void BeginSend()
        {
            Thread sendThread = new Thread(SendThread);
            sendThread.IsBackground = true;
            sendThread.Start();
        }

        private void SendThread()
        {
            Utils.watch.Reset();
            Utils.watch.Start();

            index = dir.Parent.FullName.Length + 1;
            Console.WriteLine(dir.Parent.FullName);
            GetTotalLen(dir);
            folderClient.SendString("BeginTransfer");
            folderClient.SendLong(totalLen);
            SendDir(dir);
            folderClient.SendString("EndTransfer");

            Utils.watch.Stop();
            long ms = Utils.watch.ElapsedMilliseconds;

            formMain.SetBtnEnabled("btnPathSelect", true);
            formMain.SetLable("tbStatus", "文件夹 [" + dir.Name + "] 发送完毕,用时: " + Utils.GetTime(ms) + ", 速度: " + Utils.GetSpeed(totalLen, ms) + ".");
        }

        private void SendDir(DirectoryInfo dir)
        {
            folderClient.SendString("FolderName");
            folderClient.SendString(dir.FullName.Substring(index));

            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                SendFile(file);
            }
            DirectoryInfo[] dirs = dir.GetDirectories();
            foreach (DirectoryInfo dirInfo in dirs)
            {
                SendDir(dirInfo);
            }
        }
        private long haveSendLen = 0L;
        private void SendFile(FileInfo file)
        {
            folderClient.SendString("FileTransferBegin");
            folderClient.SendString(file.Name);
            FileStream fs = fs = file.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
            try
            {
                int bufferLen = 1024 * 1024;//定义1Mb的发送缓冲区
                byte[] buffer = new byte[bufferLen];
                int readLen = 0;
                while ((readLen = fs.Read(buffer, 0, bufferLen)) != 0)
                {
                    haveSendLen += readLen;
                    folderClient.SendBytes(buffer, readLen);
                    String msg = "传送进度: " + (haveSendLen * 100 / totalLen) + " %";
                    formMain.SetLable("tbStatus", msg);
                    //Console.WriteLine(msg);
                }
                folderClient.SendInt(-1);
                fs.Close();
            }
            catch (Exception ee)
            {
                Console.WriteLine("文件传送异常: " + ee.Message);
            }
        }
    }
}
